package tkaczyk.simtalk.pc;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.regex.Pattern;

import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.JButton;

import tkaczyk.simtalk.messenger.Messenger;
import tkaczyk.simtalk.messenger.StatusDisplay;

@SuppressWarnings("serial")
public class ContentPane extends JPanel implements ActionListener, StatusDisplay {
	private Messenger messenger;
	private MessagesPane messagesPane;
	private SenderPane senderPane;
	
	private JTextField tfNick;
	private JTextField tfPort;
	private JTextField tfHost;
	private JButton btnConnect;
	private JButton btnListen;
	private JLabel lblStatus;
	private final static String CMD_CONNECT = "Connect";
	private final static String CMD_DISCONNECT = "Disconnect";
	private final static String CMD_LISTEN = "Listen";
	
	private final Pattern portPattern = Pattern.compile("^\\d{1,5}$");
	private final Pattern hostPattern = Pattern.compile("^[-.\\w]+:\\d{1,5}$");
	
	public void setMessagesPane(MessagesPane messagesPane) {
		this.messagesPane = messagesPane;
	}

	public void setSenderPane(SenderPane senderPane) {
		this.senderPane = senderPane;
	}


	public ContentPane() {
	}
	
	public void setMessenger(Messenger messenger) {
		this.messenger = messenger;
	}
	
	public void addNotify() {
		super.addNotify();
		setUpGUIElements();
		
		btnConnect.addActionListener(this);
		btnListen.addActionListener(this);
	}
	
	private void setUpGUIElements() { 
		setLayout(new MigLayout("gap rel unrel",
				"[][fill, grow 90] 20px [grow 110]",
				"[][][][grow][100px]"));

		JLabel lblNick = new JLabel("Nick:");
		add(lblNick, "cell 0 0, alignx right");

		tfNick = new JTextField();
		add(tfNick, "cell 1 0");

		JLabel lblLocalPort = new JLabel("Local port:");
		add(lblLocalPort, "cell 0 1, alignx right");

		tfPort = new JTextField();
		add(tfPort, "cell 1 1, split 2, growx");
		
		btnListen = new JButton("Listen");
		add(btnListen, "cell 1 1, wrap");

		JLabel lblRemoteHost = new JLabel("Remote host:");
		add(lblRemoteHost, "cell 0 2, alignx right");

		tfHost = new JTextField();
		add(tfHost, "cell 1 2");

		btnConnect = new JButton("Connect");
		add(btnConnect, "cell 2 0, alignx center");

		lblStatus = new JLabel("Not connected");
		lblStatus.setHorizontalAlignment(SwingConstants.CENTER);
		lblStatus.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder("Status"),
				BorderFactory.createEmptyBorder(5, 5, 8, 5)));
		add(lblStatus, "cell 2 1 1 2, grow");

		JScrollPane messagesScroll = new JScrollPane(messagesPane);
		//messagesScroll
		//		.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		add(messagesScroll, "cell 0 3 3 1, grow, wmin 10");

		JScrollPane senderScroll = new JScrollPane(senderPane);
		//messagesScroll
		//		.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		add(senderScroll, "cell 0 4 3 1, grow, wmin 10");
	}
	

	@Override
	public void actionPerformed(ActionEvent e) {
		switch (e.getActionCommand()) {
		case CMD_CONNECT:
			connect();
			break;
		case CMD_DISCONNECT:
			disconnect();
		case CMD_LISTEN:
			listen();
			break;
		}
	}

	private void listen() {
		if (portPattern.matcher(tfPort.getText()).matches()) {
			int port = Integer.parseInt(tfPort.getText());
			if (port > 0 && port < 65536) {
				messenger.listen(port);
				return;
			}
		}
		messenger.disconnect(0);
	}

	private void disconnect() {
		int port = 0;
		if (portPattern.matcher(tfPort.getText()).matches()) {
			port = Integer.parseInt(tfPort.getText());
			if (port < 1 || port > 65535) {
				port = 0;
			}
		}
		messenger.disconnect(port);
	}

	private void connect() {
		if (!hostPattern.matcher(tfHost.getText()).matches() || !portPattern.matcher(tfPort.getText()).matches()) {
			update(Status.DISCONNECTED, "Invalid connection parameters");
			return;
		}
		String[] remote = tfHost.getText().split(":");
		String remoteHost = remote[0];
		int remotePort = Integer.parseInt(remote[1]);
		int localPort = Integer.parseInt(tfPort.getText());
		if (localPort < 1 || localPort > 65535 || remotePort < 1 || remotePort > 65535) {
			update(Status.DISCONNECTED, "Invalid connection parameters");
			return;
		}
		
		messenger.connect(remoteHost, remotePort, localPort);
		
		btnListen.setEnabled(false);
		btnConnect.setText(CMD_DISCONNECT);
		btnConnect.setActionCommand(CMD_DISCONNECT);
	}

	@Override
	public void update(Status status, String statusMessage) {
		switch (status) {
		case CONNECTED:
			btnListen.setEnabled(false);
			btnConnect.setText(CMD_DISCONNECT);
			btnConnect.setActionCommand(CMD_DISCONNECT);
			break;
		case DISCONNECTED:
			btnListen.setEnabled(true);
			btnConnect.setText(CMD_CONNECT);
			btnConnect.setActionCommand(CMD_CONNECT);
			break;
		case LISTENING:
		default:
			break;
		}
		lblStatus.setText(statusMessage);
	}

	public String getNick() {
		return tfNick.getText();
	}
}
